Introdução

Análise exploratória de dados do RottenTomatoes sobre o ator Jake Gyllenhaal. O código empregado na extração dos dados aqui analizados e a descrição de como o usar encontra-se no repositório origem deste relatório.

  • Entradas que não contêm dados sobre bilheteria foram ignorados.




Data Overview

import_data("jake_gyllenhaal") 

Bilheteria

p <- filmes %>%
    ggplot(aes(x = ano, 
               y = bilheteria,
               text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m",
                            "\nAno:",ano))) + 
    geom_point(size = 4, color = paleta[1]) +
    labs(y = "Bilheteria", x = "Ano de lançamento")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Entre os filmes em que Jake atuou um foge aos outros em termos de faturamento, o memóravel blockbuster “O dia depois de amanhã” lançado em 2004.

  • É possível perceber uma tendência de queda no faturamento dos filmes em que Jake atuou após 2013.

filmes %>% 
    ggplot(aes(x = bilheteria)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = "grey", color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,200,20)) +
    labs(y = "Frequência Relativa", x = "Bilheteria")

  • Vemos claramente a disparidade entre “O dia depois de amanhã” e os outros filmes.

  • Nenhum valor fora do domínio de valores esperado, e.g. valores negativos.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = bilheteria,
               label = filme,
               text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m"))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Bilheteria")
ggplotly(p, tooltip="text") %>% 
    layout(autosize = F)
  • Separar os filmes entre os de bilheteria abaixo e acima de 50 milhões parece uma abordagem razoável.

  • “O dia depois de amanhã” aparenta formar um exército de um filme só. O que nos daria 3 grupos.

Avaliação

p <- filmes %>% 
    ggplot(aes(x = ano, 
               y = avaliacao,
                text = paste("Filme:",filme,
                            "\nAvaliação:",
                            avaliacao,
                            "\nAno:",ano))) + 
    geom_point(size = 4, color = paleta[1])  +
    scale_y_continuous(limits = c(0, 100)) +
    labs(y = "Avaliação RT", x = "Ano de lançamento")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Entre 2005 e 2010 Jake participou de uma série de filmes em particular que não agradou os críticos
  • Não aparenta haver uma tendência particularmente clara em razão do ano de lançamento.
filmes %>% 
    ggplot(aes(x = avaliacao)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = paleta[3], color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,100,10)) +
    labs(y = "Frequência Relativa", x = "Avaliação RT")

  • É possível perceber uma quantidade considerável de filmes com notas acima de 80.

  • Nenhum valor fora do domínio de valores esperado, e.g. valores negativos.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = avaliacao,
               text = paste(
                    "Filme:",filme,
                    "\nAvaliação:",avaliacao))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Avaliação RT")
ggplotly(p, tooltip = "text") %>% 
    layout(autosize = F)
  • Intuitivamente três grupos surgem:
    • Os filmes com avaliação acima de 80
    • Os filmes com avaliação entre 55 e 70
    • Os filmes com avaliação abaixo de 55




Agrupamento hierárquico



Uma dimensão


Bilheteria

agrupamento_h = filmes %>% 
    mutate(nome = paste0(filme, " (bil=", bilheteria, ")")) %>% 
    as.data.frame() %>% 
    column_to_rownames("filme") %>% 
    select(bilheteria) %>%
    dist(method = "euclidian") %>% 
    hclust(method = "centroid")
ggdendrogram(agrupamento_h, rotate = T, size = 2, theme_dendro = F) +
    labs(y = "Dissimilaridade", x = "", title = "Dendrograma") +
    geom_hline(aes(yintercept = c(20,30), color=c("4 grupos","3 grupos"))) +
    scale_colour_manual(name="#Grupos",
    values=c("#56B4E9", "#FF9999"))

  • Em termos de Dendograma a divisão em quatro grupos assim como a divisão em 3 grupos parecem ser apropriadas, dado que o aumento de dissimilaridade de 4 para 3 grupos não aparentar ser substancial.
  • Corte feito para 4 grupos
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Filmes", y = bilheteria, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    labs(y = "Bilheteria (milhões)", x = "", title = "Agrupamento com 1 Dimensão")

  • A divisão em 4 grupos parece ser mais apropriada que a divisão em 3 grupos.
    • O cluster de filmes na base do gráfico aparenta exigir um grupo próprio (Na divisão em 4 grupos seria o grupo 1).
k_escolhido = 4
m <- list(l = 220)
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, bilheteria),
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Filme:", reorder(label, bilheteria),
                    "\nAvaliação:", bilheteria,
                    "\nGrupo:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Avaliação RT") + 
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F, margin = m)
  • O dia depois de amanhã exigiu um grupo para si, como era esperado.


Avaliação

  • Em termos de Dendograma a divisão em três grupos parece ser a mais apropriada, dado que o aumento da dissimilaridade passa a ser substancial quando passamos de 3 para 2 grupos.
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Filmes", y = avaliacao, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    labs(y = "Avaliação RT", x = "", title = "Agrupamento com 1 Dimensão")

  • Visualmente a divisão em três grupos parece de fato ser apropriada, o que está em acordo com o dendograma.
k_escolhido = 3
m <- list(l = 220)
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, avaliacao),
               y = avaliacao,
               colour = grupo,
               text = paste(
                    "Filme:", reorder(label, avaliacao),
                    "\nAvaliação:", avaliacao,
                    "\nGrupo:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Avaliação RT") + 
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F, margin = m)
  • Discutivelmente, O principe da persia areias do tempo poderia exigir um grupo para si próprio.

Com duas dimensões

agrupamento_h_2d = filmes %>%
   mutate(bilheteria = log10(bilheteria)) %>%
   mutate_at(vars("avaliacao", "bilheteria"), funs(scale)) %>%
   column_to_rownames("filme") %>%
   select("avaliacao", "bilheteria") %>%
   dist(method = "euclidean") %>%
   hclust(method = "ward.D")
Setting row names on a tibble is deprecated.
ggdendrogram(agrupamento_h_2d, rotate = TRUE, theme_dendro = F) +
    labs(y = "Dissimilaridade", x = "", title = "Dendrograma")

filmes2 <- filmes %>%
    mutate(bilheteria = log10(bilheteria))
plota_hclusts_2d(agrupamento_h_2d,
                filmes2,
                c("avaliacao", "bilheteria"),
                linkage_method = "ward.D", 
                ks = 1:6,
                palette = "Dark2") + 
    scale_y_log10() +
    labs(y = "Bilheteria", x = "Avaliação", title = "Clusterização com Duas Dimensões")

atribuicoes = get_grupos(agrupamento_h_2d, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    filter(k == 3) %>%
    mutate(filme = label) %>% 
    left_join(filmes, by = "filme")
p <- atribuicoes %>%
    ggplot(aes(x = avaliacao,
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Filme:", filme,
                    "\nBilheteria:", bilheteria,"m\n",
                    "Avaliação:", avaliacao))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    scale_y_log10() +
    labs(y = "Bilheteria", x = "Avaliação RT")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
LS0tCnRpdGxlOiAiVGlwb3MgZGUgZmlsbWUgZGUgSmFrZSBHeWxsZW5oYWFsIgphdXRob3I6ICJKb3PDqSBCZW5hcmRpIGRlIFNvdXphIE51bmVzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCiMgSW50cm9kdcOnw6NvCgo+IEFuw6FsaXNlIGV4cGxvcmF0w7NyaWEgZGUgZGFkb3MgZG8gW1JvdHRlblRvbWF0b2VzXShodHRwczovL3d3dy5yb3R0ZW50b21hdG9lcy5jb20vKSBzb2JyZSBvIGF0b3IgSmFrZSBHeWxsZW5oYWFsLiBPIGPDs2RpZ28gZW1wcmVnYWRvIG5hIGV4dHJhw6fDo28gZG9zIGRhZG9zIGFxdWkgYW5hbGl6YWRvcyBlIGEgZGVzY3Jpw6fDo28gZGUgY29tbyBvIHVzYXIgZW5jb250cmEtc2Ugbm8gIFtyZXBvc2l0w7NyaW8gb3JpZ2VtXShodHRwczovL2dpdGh1Yi5jb20vQmVuYXJkaS9hZ3J1cGFtZW50by1maWxtZXMvKSBkZXN0ZSByZWxhdMOzcmlvLgoKKiBFbnRyYWRhcyBxdWUgbsOjbyBjb250w6ptIGRhZG9zIHNvYnJlIGJpbGhldGVyaWEgZm9yYW0gaWdub3JhZG9zLgoKPGJyPgoKKioqCgo8YnI+CgpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGNsdXN0ZXIpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGdnZGVuZHJvKQoKc291cmNlKGhlcmU6OmhlcmUoImNvZGUvbGliLlIiKSkKc291cmNlKGhlcmU6OmhlcmUoImNvZGUvcGxvdGFfc29sdWNvZXNfaGNsdXN0LlIiKSkKCnRoZW1lX3NldCh0aGVtZV9yZXBvcnQoKSkKCmtuaXRyOjpvcHRzX2NodW5rJHNldCh0aWR5ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGggPSA2LAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodCA9IDUsCiAgICAgICAgICAgICAgICAgICAgICBlY2hvID0gVFJVRSkKcGFsZXRhID0gYygiIzQwNEU0RCIsCiAgICAgICAgICAgIiM5MkRDRTUiLAogICAgICAgICAgICIjOTM4QkExIiwKICAgICAgICAgICAiIzJEMzE0MiIsCiAgICAgICAgICAgIiNGNDc0M0IiKQpgYGAKCiMgRGF0YSBPdmVydmlldwoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KaW1wb3J0X2RhdGEoImpha2VfZ3lsbGVuaGFhbCIpIApmaWxtZXMgPC0gcmVhZF9pbXBvcnRlZF9kYXRhKCkKZmlsbWVzICU+JSAKICAgIGdsaW1wc2UoKQpgYGAKCiMjIEJpbGhldGVyaWEKCmBgYHtyfQpwIDwtIGZpbG1lcyAlPiUKICAgIGdncGxvdChhZXMoeCA9IGFubywgCiAgICAgICAgICAgICAgIHkgPSBiaWxoZXRlcmlhLAogICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5CaWxoZXRlcmlhOiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWxoZXRlcmlhLCJtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkFubzoiLGFubykpKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gNCwgY29sb3IgPSBwYWxldGFbMV0pICsKICAgIGxhYnMoeSA9ICJCaWxoZXRlcmlhIiwgeCA9ICJBbm8gZGUgbGFuw6dhbWVudG8iKQoKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQpgYGAKCiogRW50cmUgb3MgZmlsbWVzIGVtIHF1ZSBKYWtlIGF0dW91IHVtIGZvZ2UgYW9zIG91dHJvcyBlbSB0ZXJtb3MgZGUgZmF0dXJhbWVudG8sIG8gbWVtw7NyYXZlbCBibG9ja2J1c3RlciAqKiJPIGRpYSBkZXBvaXMgZGUgYW1hbmjDoyIqKiBsYW7Dp2FkbyBlbSAyMDA0LgoKKiDDiSBwb3Nzw612ZWwgcGVyY2ViZXIgdW1hIHRlbmTDqm5jaWEgZGUgcXVlZGEgbm8gZmF0dXJhbWVudG8gZG9zIGZpbG1lcyBlbSBxdWUgSmFrZSBhdHVvdSBhcMOzcyAyMDEzLgoKYGBge3J9CmZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBiaWxoZXRlcmlhKSkgKyAKICAgIGdlb21faGlzdG9ncmFtKGFlcyh5PSguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSxiaW53aWR0aCA9IDEwLCBib3VuZGFyeSA9IDAsIAogICAgICAgICAgICAgICAgICAgZmlsbCA9ICJncmV5IiwgY29sb3IgPSAiYmxhY2siKSArIAogICAgZ2VvbV9ydWcoc2l6ZSA9IC41KSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDIwMCwyMCkpICsKICAgIGxhYnMoeSA9ICJGcmVxdcOqbmNpYSBSZWxhdGl2YSIsIHggPSAiQmlsaGV0ZXJpYSIpCgpgYGAKCiogVmVtb3MgY2xhcmFtZW50ZSBhIGRpc3BhcmlkYWRlIGVudHJlICoqIk8gZGlhIGRlcG9pcyBkZSBhbWFuaMOjIioqICBlIG9zIG91dHJvcyBmaWxtZXMuCgoqIE5lbmh1bSB2YWxvciBmb3JhIGRvIGRvbcOtbmlvIGRlIHZhbG9yZXMgZXNwZXJhZG8sIGUuZy4gdmFsb3JlcyBuZWdhdGl2b3MuCgpgYGB7cn0KcCA8LSBmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIiIsCiAgICAgICAgICAgICAgIHkgPSBiaWxoZXRlcmlhLAogICAgICAgICAgICAgICBsYWJlbCA9IGZpbG1lLAogICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5CaWxoZXRlcmlhOiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWxoZXRlcmlhLCJtIikpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDUsIGFscGhhID0gLjMsIHNpemUgPSAzKSArIAogICAgbGFicyh4ID0gIiIsIHk9IkJpbGhldGVyaWEiKQoKZ2dwbG90bHkocCwgdG9vbHRpcD0idGV4dCIpICU+JSAKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCmBgYAoKKiBTZXBhcmFyIG9zIGZpbG1lcyBlbnRyZSBvcyBkZSBiaWxoZXRlcmlhIGFiYWl4byBlIGFjaW1hIGRlIDUwIG1pbGjDtWVzIHBhcmVjZSB1bWEgYWJvcmRhZ2VtIHJhem/DoXZlbC4KCiogKioiTyBkaWEgZGVwb2lzIGRlIGFtYW5ow6MiKiogYXBhcmVudGEgZm9ybWFyIHVtIGV4w6lyY2l0byBkZSB1bSBmaWxtZSBzw7MuIE8gcXVlIG5vcyBkYXJpYSAzIGdydXBvcy4gCgojIyBBdmFsaWHDp8OjbwoKYGBge3J9CnAgPC0gZmlsbWVzICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGFubywgCiAgICAgICAgICAgICAgIHkgPSBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZhbGlhY2FvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuQW5vOiIsYW5vKSkpICsgCiAgICBnZW9tX3BvaW50KHNpemUgPSA0LCBjb2xvciA9IHBhbGV0YVsxXSkgICsKICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCkpICsKICAgIGxhYnMoeSA9ICJBdmFsaWHDp8OjbyBSVCIsIHggPSAiQW5vIGRlIGxhbsOnYW1lbnRvIikKCmdncGxvdGx5KHAsIHRvb2x0aXAgPSAidGV4dCIpICU+JQogICAgbGF5b3V0KGF1dG9zaXplID0gRikKYGBgCgoqIEVudHJlIDIwMDUgZSAyMDEwIEpha2UgcGFydGljaXBvdSBkZSB1bWEgc8OpcmllIGRlIGZpbG1lcyBlbSBwYXJ0aWN1bGFyIHF1ZSBuw6NvIGFncmFkb3Ugb3MgY3LDrXRpY29zIAoqIE7Do28gYXBhcmVudGEgaGF2ZXIgdW1hIHRlbmTDqm5jaWEgcGFydGljdWxhcm1lbnRlIGNsYXJhIGVtIHJhesOjbyBkbyBhbm8gZGUgbGFuw6dhbWVudG8uIAoKYGBge3J9CmZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBhdmFsaWFjYW8pKSArIAogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9KC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLGJpbndpZHRoID0gMTAsIGJvdW5kYXJ5ID0gMCwgCiAgICAgICAgICAgICAgICAgICBmaWxsID0gcGFsZXRhWzNdLCBjb2xvciA9ICJibGFjayIpICsgCiAgICBnZW9tX3J1ZyhzaXplID0gLjUpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDAsMTAwLDEwKSkgKwogICAgbGFicyh5ID0gIkZyZXF1w6puY2lhIFJlbGF0aXZhIiwgeCA9ICJBdmFsaWHDp8OjbyBSVCIpCgpgYGAKCiogw4kgcG9zc8OtdmVsIHBlcmNlYmVyIHVtYSBxdWFudGlkYWRlIGNvbnNpZGVyw6F2ZWwgZGUgZmlsbWVzIGNvbSBub3RhcyBhY2ltYSBkZSA4MC4KCiogTmVuaHVtIHZhbG9yIGZvcmEgZG8gZG9tw61uaW8gZGUgdmFsb3JlcyBlc3BlcmFkbywgZS5nLiB2YWxvcmVzIG5lZ2F0aXZvcy4KCgpgYGB7cn0KcCA8LSBmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIiIsCiAgICAgICAgICAgICAgIHkgPSBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLGF2YWxpYWNhbykpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDUsIGFscGhhID0gLjMsIHNpemUgPSAzKSArIAogICAgbGFicyh4ID0gIiIsIHk9IkF2YWxpYcOnw6NvIFJUIikKCmdncGxvdGx5KHAsIHRvb2x0aXAgPSAidGV4dCIpICU+JSAKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCgpgYGAKCiogSW50dWl0aXZhbWVudGUgdHLDqnMgZ3J1cG9zIHN1cmdlbToKICAgICogT3MgZmlsbWVzIGNvbSBhdmFsaWHDp8OjbyBhY2ltYSBkZSA4MAogICAgKiBPcyBmaWxtZXMgY29tIGF2YWxpYcOnw6NvIGVudHJlIDU1IGUgNzAgCiAgICAqIE9zIGZpbG1lcyBjb20gYXZhbGlhw6fDo28gYWJhaXhvIGRlIDU1Cgo8YnI+CgoqKioKCjxicj4KCiMgQWdydXBhbWVudG8gaGllcsOhcnF1aWNvCgo8YnI+Cjxicj4KCiMjIFVtYSBkaW1lbnPDo28KCjxicj4KCiMjIyBCaWxoZXRlcmlhIAoKYGBge3J9CmFncnVwYW1lbnRvX2ggPSBmaWxtZXMgJT4lIAogICAgbXV0YXRlKG5vbWUgPSBwYXN0ZTAoZmlsbWUsICIgKGJpbD0iLCBiaWxoZXRlcmlhLCAiKSIpKSAlPiUgCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgY29sdW1uX3RvX3Jvd25hbWVzKCJmaWxtZSIpICU+JSAKICAgIHNlbGVjdChiaWxoZXRlcmlhKSAlPiUKICAgIGRpc3QobWV0aG9kID0gImV1Y2xpZGlhbiIpICU+JSAKICAgIGhjbHVzdChtZXRob2QgPSAiY2VudHJvaWQiKQoKZ2dkZW5kcm9ncmFtKGFncnVwYW1lbnRvX2gsIHJvdGF0ZSA9IFQsIHNpemUgPSAyLCB0aGVtZV9kZW5kcm8gPSBGKSArCiAgICBsYWJzKHkgPSAiRGlzc2ltaWxhcmlkYWRlIiwgeCA9ICIiLCB0aXRsZSA9ICJEZW5kcm9ncmFtYSIpICsKICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBjKDIwLDMwKSwgY29sb3I9YygiNCBncnVwb3MiLCIzIGdydXBvcyIpKSkgKwogICAgc2NhbGVfY29sb3VyX21hbnVhbChuYW1lPSIjR3J1cG9zIiwKICAgIHZhbHVlcz1jKCIjNTZCNEU5IiwgIiNGRjk5OTkiKSkKYGBgCgoqIEVtIHRlcm1vcyBkZSBEZW5kb2dyYW1hIGEgZGl2aXPDo28gZW0gcXVhdHJvIGdydXBvcyBhc3NpbSBjb21vIGEgZGl2aXPDo28gZW0gMyBncnVwb3MgcGFyZWNlbSBzZXIgYXByb3ByaWFkYXMsIGRhZG8gcXVlIG8gYXVtZW50byBkZSBkaXNzaW1pbGFyaWRhZGUgZGUgNCBwYXJhIDMgZ3J1cG9zIG7Do28gYXBhcmVudGFyIHNlciBzdWJzdGFuY2lhbC4KKiAgQ29ydGUgZmVpdG8gcGFyYSA0IGdydXBvcwoKYGBge3J9CmF0cmlidWljb2VzID0gZ2V0X2dydXBvcyhhZ3J1cGFtZW50b19oLCBudW1fZ3J1cG9zID0gMTo2KQoKYXRyaWJ1aWNvZXMgPSBhdHJpYnVpY29lcyAlPiUgCiAgICBsZWZ0X2pvaW4oZmlsbWVzLCBieSA9IGMoImxhYmVsIiA9ICJmaWxtZSIpKQoKYXRyaWJ1aWNvZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIkZpbG1lcyIsIHkgPSBiaWxoZXRlcmlhLCBjb2xvdXIgPSBncnVwbykpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wMiwgaGVpZ2h0ID0gMCwgc2l6ZSA9IDEuNiwgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgICBsYWJzKHkgPSAiQmlsaGV0ZXJpYSAobWlsaMO1ZXMpIiwgeCA9ICIiLCB0aXRsZSA9ICJBZ3J1cGFtZW50byBjb20gMSBEaW1lbnPDo28iKQoKYGBgCgoqIEEgZGl2aXPDo28gZW0gNCBncnVwb3MgcGFyZWNlIHNlciBtYWlzIGFwcm9wcmlhZGEgcXVlIGEgZGl2aXPDo28gZW0gMyBncnVwb3MuCiAgICAqIE8gY2x1c3RlciBkZSBmaWxtZXMgbmEgYmFzZSBkbyBncsOhZmljbyBhcGFyZW50YSBleGlnaXIgdW0gZ3J1cG8gcHLDs3ByaW8gKE5hIGRpdmlzw6NvIGVtIDQgZ3J1cG9zIHNlcmlhIG8gZ3J1cG8gMSkuIAoKYGBge3J9CmtfZXNjb2xoaWRvID0gNAoKbSA8LSBsaXN0KGwgPSAyMjApCgpwIDwtYXRyaWJ1aWNvZXMgJT4lIAogICAgZmlsdGVyKGsgPT0ga19lc2NvbGhpZG8pICU+JSAKICAgIGdncGxvdChhZXMoeCA9IHJlb3JkZXIobGFiZWwsIGJpbGhldGVyaWEpLAogICAgICAgICAgICAgICB5ID0gYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IiwgcmVvcmRlcihsYWJlbCwgYmlsaGV0ZXJpYSksCiAgICAgICAgICAgICAgICAgICAgIlxuQXZhbGlhw6fDo286IiwgYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgICAgICAiXG5HcnVwbzoiLCBncnVwbykpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDIsIGhlaWdodCA9IDAsIHNpemUgPSAzLCBhbHBoYSA9IC42KSArIAogICAgZmFjZXRfd3JhcCh+IHBhc3RlKGssICIgZ3J1cG9zIikpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsgCiAgICBsYWJzKHggPSAiIiwgeSA9ICJBdmFsaWHDp8OjbyBSVCIpICsgCiAgICBjb29yZF9mbGlwKCkKCmdncGxvdGx5KHAsdG9vbHRpcCA9ICJ0ZXh0IikgJT4lCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGLCBtYXJnaW4gPSBtKQoKYGBgCgoqICoqTyBkaWEgZGVwb2lzIGRlIGFtYW5ow6MqKiBleGlnaXUgdW0gZ3J1cG8gcGFyYSBzaSwgY29tbyBlcmEgZXNwZXJhZG8uCgo8YnI+CgojIyMgQXZhbGlhw6fDo28gCgpgYGB7cn0KYWdydXBhbWVudG9faCA9IGZpbG1lcyAlPiUgCiAgICBtdXRhdGUobm9tZSA9IHBhc3RlMChmaWxtZSwgIiAoYXY9IiwgYXZhbGlhY2FvLCAiKSIpKSAlPiUgCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgY29sdW1uX3RvX3Jvd25hbWVzKCJmaWxtZSIpICU+JSAKICAgIHNlbGVjdChhdmFsaWFjYW8pICU+JQogICAgZGlzdChtZXRob2QgPSAiZXVjbGlkaWFuIikgJT4lIAogICAgaGNsdXN0KG1ldGhvZCA9ICJ3YXJkLkQiKQoKZ2dkZW5kcm9ncmFtKGFncnVwYW1lbnRvX2gsIHJvdGF0ZSA9IFQsIHNpemUgPSAyLCB0aGVtZV9kZW5kcm8gPSBGKSArCiAgICBsYWJzKHkgPSAiRGlzc2ltaWxhcmlkYWRlIiwgeCA9ICIiLCB0aXRsZSA9ICJEZW5kcm9ncmFtYSIpICsKICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAzMCksY29sb3I9InJlZCIpCmBgYAoKKiBFbSB0ZXJtb3MgZGUgRGVuZG9ncmFtYSBhICoqZGl2aXPDo28gZW0gdHLDqnMgZ3J1cG9zIHBhcmVjZSBzZXIgYSBtYWlzIGFwcm9wcmlhZGEqKiwgZGFkbyBxdWUgbyBhdW1lbnRvIGRhIGRpc3NpbWlsYXJpZGFkZSBwYXNzYSBhIHNlciBzdWJzdGFuY2lhbCBxdWFuZG8gcGFzc2Ftb3MgZGUgMyBwYXJhIDIgZ3J1cG9zLgoKYGBge3J9CmF0cmlidWljb2VzID0gZ2V0X2dydXBvcyhhZ3J1cGFtZW50b19oLCBudW1fZ3J1cG9zID0gMTo2KQoKYXRyaWJ1aWNvZXMgPSBhdHJpYnVpY29lcyAlPiUgCiAgICBsZWZ0X2pvaW4oZmlsbWVzLCBieSA9IGMoImxhYmVsIiA9ICJmaWxtZSIpKQoKYXRyaWJ1aWNvZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIkZpbG1lcyIsIHkgPSBhdmFsaWFjYW8sIGNvbG91ciA9IGdydXBvKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMS42LCBhbHBoYSA9IC42KSArIAogICAgZmFjZXRfd3JhcCh+IHBhc3RlKGssICIgZ3J1cG9zIikpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsKICAgIGxhYnMoeSA9ICJBdmFsaWHDp8OjbyBSVCIsIHggPSAiIiwgdGl0bGUgPSAiQWdydXBhbWVudG8gY29tIDEgRGltZW5zw6NvIikKCmBgYAoKKiBWaXN1YWxtZW50ZSBhIGRpdmlzw6NvIGVtIHRyw6pzIGdydXBvcyBwYXJlY2UgZGUgZmF0byBzZXIgYXByb3ByaWFkYSwgbyBxdWUgZXN0w6EgZW0gYWNvcmRvIGNvbSBvIGRlbmRvZ3JhbWEuCgpgYGB7cn0Ka19lc2NvbGhpZG8gPSAzCgptIDwtIGxpc3QobCA9IDIyMCkKCnAgPC1hdHJpYnVpY29lcyAlPiUgCiAgICBmaWx0ZXIoayA9PSBrX2VzY29saGlkbykgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihsYWJlbCwgYXZhbGlhY2FvKSwKICAgICAgICAgICAgICAgeSA9IGF2YWxpYWNhbywKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IiwgcmVvcmRlcihsYWJlbCwgYXZhbGlhY2FvKSwKICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLCBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgICAgICAgIlxuR3J1cG86IiwgZ3J1cG8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArIAogICAgbGFicyh4ID0gIiIsIHkgPSAiQXZhbGlhw6fDo28gUlQiKSArIAogICAgY29vcmRfZmxpcCgpCgpnZ3Bsb3RseShwLHRvb2x0aXAgPSAidGV4dCIpICU+JQogICAgbGF5b3V0KGF1dG9zaXplID0gRiwgbWFyZ2luID0gbSkKCmBgYAoKKiBEaXNjdXRpdmVsbWVudGUsICoqTyBwcmluY2lwZSBkYSBwZXJzaWEgYXJlaWFzIGRvIHRlbXBvKiogcG9kZXJpYSBleGlnaXIgdW0gZ3J1cG8gcGFyYSBzaSBwcsOzcHJpby4KCiMjIENvbSBkdWFzIGRpbWVuc8O1ZXMKCmBgYHtyfQphZ3J1cGFtZW50b19oXzJkID0gZmlsbWVzICU+JQogICBtdXRhdGUoYmlsaGV0ZXJpYSA9IGxvZzEwKGJpbGhldGVyaWEpKSAlPiUKICAgbXV0YXRlX2F0KHZhcnMoImF2YWxpYWNhbyIsICJiaWxoZXRlcmlhIiksIGZ1bnMoc2NhbGUpKSAlPiUKICAgY29sdW1uX3RvX3Jvd25hbWVzKCJmaWxtZSIpICU+JQogICBzZWxlY3QoImF2YWxpYWNhbyIsICJiaWxoZXRlcmlhIikgJT4lCiAgIGRpc3QobWV0aG9kID0gImV1Y2xpZGVhbiIpICU+JQogICBoY2x1c3QobWV0aG9kID0gIndhcmQuRCIpCgpnZ2RlbmRyb2dyYW0oYWdydXBhbWVudG9faF8yZCwgcm90YXRlID0gVFJVRSwgdGhlbWVfZGVuZHJvID0gRikgKwogICAgbGFicyh5ID0gIkRpc3NpbWlsYXJpZGFkZSIsIHggPSAiIiwgdGl0bGUgPSAiRGVuZHJvZ3JhbWEiKQpgYGAKCmBgYHtyfQpmaWxtZXMyIDwtIGZpbG1lcyAlPiUKICAgIG11dGF0ZShiaWxoZXRlcmlhID0gbG9nMTAoYmlsaGV0ZXJpYSkpCgpwbG90YV9oY2x1c3RzXzJkKGFncnVwYW1lbnRvX2hfMmQsCiAgICAgICAgICAgICAgICBmaWxtZXMyLAogICAgICAgICAgICAgICAgYygiYXZhbGlhY2FvIiwgImJpbGhldGVyaWEiKSwKICAgICAgICAgICAgICAgIGxpbmthZ2VfbWV0aG9kID0gIndhcmQuRCIsIAogICAgICAgICAgICAgICAga3MgPSAxOjYsCiAgICAgICAgICAgICAgICBwYWxldHRlID0gIkRhcmsyIikgKyAKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHkgPSAiQmlsaGV0ZXJpYSIsIHggPSAiQXZhbGlhw6fDo28iLCB0aXRsZSA9ICJDbHVzdGVyaXphw6fDo28gY29tIER1YXMgRGltZW5zw7VlcyIpCmBgYAoKYGBge3J9CmF0cmlidWljb2VzID0gZ2V0X2dydXBvcyhhZ3J1cGFtZW50b19oXzJkLCBudW1fZ3J1cG9zID0gMTo2KQoKYXRyaWJ1aWNvZXMgPSBhdHJpYnVpY29lcyAlPiUgCiAgICBmaWx0ZXIoayA9PSAzKSAlPiUKICAgIG11dGF0ZShmaWxtZSA9IGxhYmVsKSAlPiUgCiAgICBsZWZ0X2pvaW4oZmlsbWVzLCBieSA9ICJmaWxtZSIpCgpwIDwtIGF0cmlidWljb2VzICU+JQogICAgZ2dwbG90KGFlcyh4ID0gYXZhbGlhY2FvLAogICAgICAgICAgICAgICB5ID0gYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IiwgZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgIlxuQmlsaGV0ZXJpYToiLCBiaWxoZXRlcmlhLCJtXG4iLAogICAgICAgICAgICAgICAgICAgICJBdmFsaWHDp8OjbzoiLCBhdmFsaWFjYW8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh5ID0gIkJpbGhldGVyaWEiLCB4ID0gIkF2YWxpYcOnw6NvIFJUIikKCgpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCmBgYAo=